﻿using System;
using System.Collections.Generic;
using System.Web;

using WxPayAPI;
using Aden.Model.WeChat;
using Aden.Util.Database;
using Aden.Util.Common;
using System.Collections;
using System.Text;
using System.Security.Cryptography;

namespace Aden.DAL.Wechat
{
    public class MastDataFactory
    {
        private static JSAPI_TICKET jsapi_tickect = new JSAPI_TICKET();
        private static ACCESS_TOKEN access_token = new ACCESS_TOKEN();

        private WeChatConfig wcf = null;
        public MastDataFactory(string appName = null)
        {
            if (string.IsNullOrWhiteSpace(appName)) return;

            string strSql = " SELECT * " +
                " FROM TBLWECHATCONFIG (nolock) " +
            " WHERE APPNAME = '{0}' ";

            strSql = string.Format(strSql, appName);
            System.Data.DataTable dt = SqlServerHelper.GetDataTable(SqlServerHelper.salesorderConn(), strSql);
            wcf = SqlServerHelper.GetEntity<WeChatConfig>(SqlServerHelper.salesorderConn(), strSql);

        }

        public Dictionary<string, object> GetUserInfo(string code)
        {
            //检测必填参数
            if (string.IsNullOrWhiteSpace(code))
                throw new WxPayException("微信认证缺少必填参数code！");

            try
            {
                Dictionary<string, string> menu = GetOpenId(code).JSDeserialize<Dictionary<string, string>>();

                string openid = menu["openid"];
                string access_token = menu["access_token"];

                string url = $"https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}";

                string jsonStr = HttpService.Get(url);//Get请求
                Dictionary<string, object> dic = jsonStr.JSDeserialize<Dictionary<string, object>>();

                if (dic.ContainsKey("errmsg"))
                    throw new Exception(dic["errmsg"].ToString());

                dic.Add("appId", wcf.appId);
                //dic.Add("nonceStr", GetNonceStr());
                //dic.Add("timeStamp", GetTimeStamp());
                //dic.Add("signature", GetSignature(weburl));

                return dic;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        public string GetUserInfo()
        {
            try
            {
                string code = GetCode();

                Dictionary<string, string> menu = GetOpenId(code).JSDeserialize<Dictionary<string, string>>();

                string openid = menu["openid"];
                string access_token = menu["access_token"];

                string url = "https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}";
                url = string.Format(url, access_token, openid);

                string jsonStr = HttpService.Get(url);//Get请求

                if (jsonStr.Contains("errmsg"))
                    throw new Exception(jsonStr);

                return jsonStr;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public string GetCodeUrl(string redirectUrl)
        {
            try
            {
                if (wcf == null) throw new Exception("没有获得微信的id");

                if (redirectUrl.ToLower().Contains("localhost"))
                    redirectUrl = "https://mall.adenchina.net";
                string url = "https://open.weixin.qq.com/connect/oauth2/authorize?";
                url = $"{url}appid={wcf.appId}&redirect_uri={redirectUrl}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";

                return url;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        private string GetOpenId(string code)
        {

            //检测必填参数
            if (string.IsNullOrWhiteSpace(code))
                throw new Exception("微信认证缺少必填参数code！");

            string openid = string.Empty;

            string url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
            url = string.Format(url, wcf.appId, wcf.appSecret, code);

            string jsonStr = HttpService.Get(url);//Get请求

            // 解析JSON字符串
            //Dictionary<string, string> menu = jsonStr.JSDeserialize<Dictionary<string, string>>();

            if (jsonStr.Contains("errmsg"))
                throw new Exception(jsonStr.JSDeserialize<Dictionary<string, string>>()["errmsg"]);

            //menu.TryGetValue("openid", out openid);

            return jsonStr;// openid;
        }

        private string GetCode()
        {

            HttpRequest request = HttpContext.Current.Request;
            string code = request.QueryString["code"];
            //if (!string.IsNullOrWhiteSpace(code)) return GetOpenId(code);

            try
            {
                if (wcf == null) throw new Exception("没有获得微信的id");

                string redirecturl = request.Url.AbsoluteUri + @"/";
                if (redirecturl.ToLower().Contains("localhost"))
                    redirecturl = "https://mall.adenchina.net";
                string url = "https://open.weixin.qq.com/connect/oauth2/authorize?";
                url = $"{url}appid={wcf.appId}&redirect_uri={redirecturl}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";

                HttpContext.Current.Response.Redirect(url);
                HttpContext.Current.Response.End();

                return null;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        private string GetSignature(string url)
        {
            var parameters = new Hashtable();
            parameters.Add("jsapi_ticket", GetJSApiTicket());
            parameters.Add("noncestr", GetNonceStr());
            parameters.Add("timestamp", GetTimeStamp());
            parameters.Add("url", url);
            return CreateSha1(parameters);
        }

        private string CreateSha1(Hashtable parameters)
        {
            var sb = new StringBuilder();
            var akeys = new ArrayList(parameters.Keys);
            akeys.Sort();

            foreach (var k in akeys)
            {
                if (parameters[k] != null)
                {
                    var v = (string)parameters[k];

                    if (sb.Length == 0)
                    {
                        sb.Append(k + "=" + v);
                    }
                    else
                    {
                        sb.Append("&" + k + "=" + v);
                    }
                }
            }
            return GetSha1(sb.ToString()).ToLower();
        }

        private string GetSha1(string str)
        {
            //建立SHA1对象
            SHA1 sha = new SHA1CryptoServiceProvider();
            //将mystr转换成byte[] 
            ASCIIEncoding enc = new ASCIIEncoding();
            byte[] dataToHash = enc.GetBytes(str);
            //Hash运算
            byte[] dataHashed = sha.ComputeHash(dataToHash);
            //将运算结果转换成string
            string hash = BitConverter.ToString(dataHashed).Replace("-", "");
            return hash;
        }

        /// <summary>
        /// 获取凭证接口
        /// </summary>
        /// <param name="grant_type">获取access_token填写client_credential</param>
        /// <param name="appid">第三方用户唯一凭证</param>
        /// <param name="secret">第三方用户唯一凭证密钥，既appsecret</param>
        /// <returns></returns>
        private string GetAccessToken()
        {
            try
            {
                var url = "http://mall.adenchina.net/jc/api/AccessToken.ashx";
                string jsonStr;
                if (wcf.appName.ToLower().Equals("officialaccount"))
                {
                    jsonStr = HttpService.Get(url);
                    return jsonStr;
                }

                if (!access_token.isExired()) return access_token.token;

                access_token.CreateTime = DateTime.Now;

                url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={wcf.appId}&secret={wcf.appSecret}";
                jsonStr = HttpService.Get(url);

                Dictionary<string, string> dic = jsonStr.JSDeserialize<Dictionary<string, string>>();
                if (dic.ContainsKey("errmsg")) throw new Exception(dic["errmsg"]);

                access_token.token = dic["access_token"];
                return access_token.token;                
            }
            catch(Exception e)
            {
                throw e;
            }

        }

        public string GetJSApiTicket()
        {
            try
            {
                if (!jsapi_tickect.isExired()) return jsapi_tickect.ticket;

                jsapi_tickect.CreateTime = DateTime.Now;

                string url = $"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={GetAccessToken()}&type=jsapi";
                string jsonStr = HttpService.Get(url);
                Dictionary<string, string> dic = jsonStr.JSDeserialize<Dictionary<string, string>>();

                if (dic["errmsg"] != "ok") throw new Exception(dic["errmsg"]);

                jsapi_tickect.ticket = dic["ticket"];
                return jsapi_tickect.ticket;
            }
            catch(Exception e)
            {
                throw e;
            }
        }
        /**
        * 生成随机串，随机串包含字母或数字
        * @return 随机串
        */
        private string GetNonceStr()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
        }

        /**
        * 生成时间戳，标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
         * @return 时间戳
        */
        private string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
    }

    public class JSAPI_TICKET
    {
        public string ticket;
        public DateTime CreateTime;
        public bool isExired()
        {
            return string.IsNullOrWhiteSpace(ticket) ||
                (CreateTime == null) ||
                ((DateTime.Now - CreateTime).TotalSeconds > 7200);
        }
    }

    public class ACCESS_TOKEN
    {
        public string token;
        public DateTime CreateTime;
        public bool isExired()
        {
            return string.IsNullOrWhiteSpace(token) ||
                (CreateTime == null) ||
                ((DateTime.Now - CreateTime).TotalSeconds > 7200);
        }
    }
}
